package com.greensam.pixelengine.facade.impl;

import cn.hutool.core.bean.BeanUtil;
import com.greensam.pixelengine.exception.BusinessException;
import com.greensam.pixelengine.exception.ResultCode;
import com.greensam.pixelengine.exception.ThrowUtils;
import com.greensam.pixelengine.facade.SpaceFacadeService;
import com.greensam.pixelengine.pojo.base.DeleteRequest;
import com.greensam.pixelengine.pojo.base.PaginationResponse;
import com.greensam.pixelengine.pojo.emuns.*;
import com.greensam.pixelengine.pojo.entity.RolePo;
import com.greensam.pixelengine.pojo.entity.SpacePo;
import com.greensam.pixelengine.pojo.entity.SpaceUserPo;
import com.greensam.pixelengine.pojo.entity.UserRolePo;
import com.greensam.pixelengine.pojo.query.SpacePageQuery;
import com.greensam.pixelengine.pojo.vo.space.request.SpaceCreateRequest;
import com.greensam.pixelengine.pojo.vo.space.request.SpaceEditRequest;
import com.greensam.pixelengine.pojo.vo.space.request.SpacePageRequest;
import com.greensam.pixelengine.pojo.vo.space.request.SpaceUpdateRequest;
import com.greensam.pixelengine.pojo.vo.space.response.SpaceLevelVo;
import com.greensam.pixelengine.pojo.vo.space.response.SpaceVo;
import com.greensam.pixelengine.service.RoleDataService;
import com.greensam.pixelengine.service.SpaceDataService;
import com.greensam.pixelengine.service.SpaceUserDataService;
import com.greensam.pixelengine.service.UserDataService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author Ma Chengrui
 * @since 2025/8/2 14:23
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SpaceFacadeServiceImpl implements SpaceFacadeService {

    private final RoleDataService roleDataService;
    private final UserDataService userDataService;
    private final SpaceDataService spaceDataService;
    private final SpaceUserDataService spaceUserDataService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createSpace(SpaceCreateRequest request, Long userId) {
        SpacePo spacePo = BeanUtil.copyProperties(request, SpacePo.class);
        if (StringUtils.isBlank(spacePo.getName())) {
            spacePo.setName("未命名空间");
        }
        if (Objects.isNull(spacePo.getLevel())) {
            spacePo.setLevel(SpaceLevelEnum.COMMON);
        } else {
            spacePo.setLevel(SpaceLevelEnum.getByValue(request.getLevel()));
        }
        // 按照空间等级填充空间大小
        fillSpaceMaxSizeByLevel(spacePo);
        if (Objects.isNull(spacePo.getType())) {
            spacePo.setType(SpaceTypeEnum.PRIVATE);
        } else {
            spacePo.setType(SpaceTypeEnum.getByValue(request.getType()));
        }

        // 校验
        validSpace(spacePo, Boolean.TRUE);
        // 保存空间，同一用户只能创建一个私有空间以及一个团队空间
        ThrowUtils.throwIf(spaceDataService.getSpaceByUserId(userId, spacePo.getType()).isPresent(), ErrorCodeEnum.OperationDataError, "每个用户每类空间只能创建一个");
        spacePo.setCreateBy(userId);
        spacePo.setUpdateBy(userId);
        spacePo.setDelete(Boolean.FALSE);
        try {
            SpacePo save = spaceDataService.save(spacePo);
            log.info("创建空间成功：{}", spacePo);

            // 如果创建的是团队空间，关联空间用户角色，自动设置为空间管理员
            if (spacePo.getType() == SpaceTypeEnum.TEAM) {
                SpaceUserPo spaceUserPo = new SpaceUserPo();
                spaceUserPo.setCreateBy(userId);
                spaceUserPo.setUpdateBy(userId);
                spaceUserPo.setSpaceId(spacePo.getId());
                spaceUserPo.setSpaceName(spacePo.getName());
                userDataService.getUserById(userId).ifPresent(userPo -> {
                    spaceUserPo.setUserId(userPo.getId());
                    spaceUserPo.setUserName(userPo.getName());
                });

                Optional<RolePo> rolePoByCode = roleDataService.getRolePoByCode(TeamSpaceRoleEnum.SUPERVISOR.getCode());
                // 校验角色
                ThrowUtils.throwIf(rolePoByCode.isEmpty(), ErrorCodeEnum.OperationDataError, "创建团队空间失败，请检查是否存在团队管理员角色");

                RolePo role = rolePoByCode.get();
                spaceUserPo.setRoleId(role.getId());
                spaceUserPo.setRoleCode(role.getCode());
                spaceUserPo.setRoleName(role.getName());
                SpaceUserPo spaceUserSave = spaceUserDataService.save(spaceUserPo);
                log.info("创建团队空间，自动设置创建人为空间管理员：{}", spaceUserSave);

                // 创建团队空间之后，自动关联用户角色
                UserRolePo userRolePo = new UserRolePo();
                userRolePo.setCreateBy(userId);
                userRolePo.setUpdateBy(userId);
                userRolePo.setUserId(userId);
                userRolePo.setRoleId(role.getId());
                userRolePo.setStatus(StatusEnum.Approved);
                userDataService.saveUserRole(userRolePo);
                log.info("创建团队空间，自动关联用户角色：{}", userRolePo);
            }
            return save.getId();
        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.OperationDataError, "创建空间失败");
        }
    }

    @Override
    public Boolean deleteSpace(DeleteRequest request, Long userId) {
        spaceDataService.getSpaceById(request.getId()).ifPresent(spacePo -> {
            // 校验权限
            validSpaceOperationAuth(userId, spacePo);
            spacePo.setUpdateBy(userId);
            spacePo.setDelete(Boolean.TRUE);
            spaceDataService.save(spacePo);
            log.info("删除空间成功：{}", spacePo);
            // todo 删除空间同步删除空间中的图片 空间用户关系 还要分空间类型删除用户角色
        });
        return Boolean.TRUE;
    }

    @Override
    public Boolean editSpace(SpaceEditRequest request, Long userId) {
        spaceDataService.getSpaceById(request.getId()).ifPresent(spacePo -> {
            // 校验权限
            validSpaceOperationAuth(userId, spacePo);
            if (StringUtils.isNotBlank(request.getName())) {
                spacePo.setName(request.getName());
            }
            if (StringUtils.isNotBlank(request.getDescription())) {
                spacePo.setDescription(request.getDescription());
            }
            spacePo.setUpdateBy(userId);
            // 校验数据
            validSpace(spacePo, Boolean.FALSE);
            spaceDataService.save(spacePo);
            log.info("编辑空间成功：{}", spacePo);
        });
        return Boolean.TRUE;
    }

    @Override
    public SpaceVo getSpaceById(Long id) {
        ThrowUtils.throwIf(Objects.isNull(id), ErrorCodeEnum.ParamValidError);
        SpacePo spacePo = spaceDataService.getSpaceById(id)
                .orElseThrow(() -> new BusinessException(ErrorCodeEnum.SpaceNotExist, "空间不存在"));
        return SpaceVo.spacePo2Vo(spacePo);
    }

    @Override
    public SpaceVo getSpaceDetail(Long id) {
        ThrowUtils.throwIf(Objects.isNull(id), ErrorCodeEnum.ParamValidError);
        SpacePo spacePo = spaceDataService.getSpaceById(id)
                .orElseThrow(() -> new BusinessException(ErrorCodeEnum.SpaceNotExist, "空间不存在"));
        return SpaceVo.spacePo2Vo(spacePo);
    }

    @Override
    public PaginationResponse<SpaceVo> pageSpace(SpacePageRequest request) {
        SpacePageQuery pageQuery = BeanUtil.copyProperties(request, SpacePageQuery.class);
        pageQuery.setLevel(SpaceLevelEnum.getByValue(request.getLevel()));
        PaginationResponse<SpacePo> pageResponse = spaceDataService.pageSpace(pageQuery);
        if (pageResponse.isEmpty()) {
            return PaginationResponse.empty(pageQuery.getPageSize(), pageQuery.getPageNum());
        }
        return pageResponse.map(SpaceVo::spacePo2Vo);
    }

    @Override
    public Boolean updateSpace(SpaceUpdateRequest request, Long userId) {
        spaceDataService.getSpaceById(request.getId()).ifPresent(spacePo -> {
            // 校验权限
            validSpaceOperationAuth(userId, spacePo);
            if (StringUtils.isNotBlank(request.getName())) {
                spacePo.setName(request.getName());
            }
            if (StringUtils.isNotBlank(request.getDescription())) {
                spacePo.setDescription(request.getDescription());
            }
            if (request.getLevel() != null) {
                spacePo.setLevel(SpaceLevelEnum.getByValue(request.getLevel()));
                // 设置空间大小
                fillSpaceMaxSizeByLevel(spacePo);
            }
            spacePo.setUpdateBy(userId);
            // 校验数据
            validSpace(spacePo, Boolean.FALSE);
            spaceDataService.save(spacePo);
            log.info("更新空间成功：{}", spacePo);
        });
        return Boolean.TRUE;
    }

    @Override
    public List<SpaceLevelVo> listSpaceLevel() {
        List<SpaceLevelVo> vos = new ArrayList<>();
        for (SpaceLevelEnum value : SpaceLevelEnum.values()) {
            SpaceLevelVo vo = new SpaceLevelVo();
            vo.setValue(value.getValue());
            vo.setDesc(value.getDesc());
            vo.setMaxSize(value.getMaxSize());
            vos.add(vo);
        }
        return vos;
    }

    /**
     * 根据实体中的等级设置空间最大大小
     *
     * @param spacePo 空间实体
     * @author Ma Chengrui
     * @since 2025/8/2
     */
    public void fillSpaceMaxSizeByLevel(SpacePo spacePo) {
        SpaceLevelEnum spaceLevelEnum = spacePo.getLevel();
        if (Objects.nonNull(spaceLevelEnum)) {
            long maxSize = spaceLevelEnum.getMaxSize();
            if (Objects.isNull(spacePo.getMaxSize()) || spacePo.getMaxSize() != maxSize) {
                spacePo.setMaxSize(maxSize);
            }
        }
    }

    /**
     * 校验空间数据是否符合数据库要求
     *
     * @param spacePo 空间实体
     * @param create  是否是创建空间
     * @author Ma Chengrui
     * @since 2025/9/16
     */
    public void validSpace(SpacePo spacePo, Boolean create) {
        ThrowUtils.throwIf(Objects.isNull(spacePo), ErrorCodeEnum.ParamValidError);
        String name = spacePo.getName();
        SpaceLevelEnum spaceLevel = spacePo.getLevel();
        SpaceTypeEnum spaceType = spacePo.getType();
        if (create) {
            ThrowUtils.throwIf(StringUtils.isBlank(name), ErrorCodeEnum.ParamValidError, "空间名称不能为空");
            ThrowUtils.throwIf(Objects.isNull(spaceLevel), ErrorCodeEnum.ParamValidError, "空间等级不能为空");
            ThrowUtils.throwIf(Objects.isNull(spaceType), ErrorCodeEnum.ParamValidError, "空间类型不能为空");
        }
        ThrowUtils.throwIf(StringUtils.isNotBlank(name) && name.length() > 50, ErrorCodeEnum.ParamValidError, "空间名称过长");
    }

    /**
     * 校验空间操作权限
     *
     * @param userId  用户id
     * @param spacePo 空间实体
     * @author Ma Chengrui
     * @since 2025/9/16
     */
    private void validSpaceOperationAuth(Long userId, SpacePo spacePo) {
        if (!spacePo.getCreateBy().equals(userId) && !roleDataService.isAdmin(userId)) {
            throw new BusinessException(ResultCode.NO_AUTH_ERROR, "仅本人或管理员可以操作");
        }
    }
}
